home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 476-500 / disk_498 / zoomdaemon / source / zoom-handler.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  15KB  |  486 lines

  1. /*
  2.  *  ZOOM-DAEMON   A program that implements Zoom gadgets for all Intuition
  3.  *                windows that are opened while it is running.
  4.  *
  5.  *              Copyright 1989 by Davide P. Cervone.
  6.  *  You may use this code, provided this copyright notice is kept intact.
  7.  */
  8.  
  9. #include "Zoom-Handler.h"
  10.  
  11. static char *program   = PROGRAM;
  12. static char *copyright = COPYRIGHT;
  13.  
  14. struct ExtGadget *FirstZoom;                /* Linked list of Zoom Gadgets */
  15.  
  16.  
  17. /*
  18.  *  The Image structures for the HIRES and LOWRES Zoom Gadgets
  19.  */
  20.  
  21. static struct Image ZoomImage =
  22.    {-6,0, ZOOMWIDTH,ZOOMHEIGHT,ZOOMDEPTH, &ZoomData[0][0], 0x03,0x00, NULL};
  23.  
  24. static struct Image LR_ZoomImage =
  25.    {-4,0, LRZOOMWIDTH,LRZOOMHEIGHT,LRZOOMDEPTH, &LR_ZoomData[0][0],
  26.    0x03,0x00,NULL};
  27.  
  28. /*
  29.  *  Templates for the HIRES and LOWRES Zoom Gadgets (copied when a new
  30.  *  instance of a Zoom Gadget is created).
  31.  */
  32.  
  33. static struct ExtGadget ZoomGadget =
  34. {
  35.    NULL,NULL, NULL, 0,0,0,0, 0,
  36.    {NULL, 0,0, 21,10, GADGHCOMP | GADGIMAGE | GRELRIGHT,
  37.    RELVERIFY | TOPBORDER, SYSGADGET | BOOLGADGET, (APTR)&ZoomImage,
  38.    NULL, NULL, 0, NULL, ZOOMGADG, NULL}
  39. };
  40.  
  41. static struct ExtGadget LR_ZoomGadget =
  42. {
  43.    NULL,NULL, NULL, 0,0,0,0, 0,
  44.    {NULL, 0,0, 15,10, GADGHCOMP | GADGIMAGE | GRELRIGHT,
  45.    RELVERIFY | TOPBORDER, SYSGADGET | BOOLGADGET, (APTR)&LR_ZoomImage,
  46.    NULL, NULL, 0, NULL, ZOOMGADG, NULL}
  47. };
  48.  
  49.  
  50. /*
  51.  *  PositionZoomGadget()
  52.  *
  53.  *  Finds the position for the zoom gadget by checking for GRELRIGHT
  54.  *  gadgets in the window's gadget list.  Gadgets in the TOPBORDER are
  55.  *  counted, but since the DEPTH gadgets are not listed with TOPBORDER
  56.  *  flags set, we also check for SYSGADGETs that are GRELGADGETs but not
  57.  *  GRELBOTTOM gadgets (the SIZING gadget is GRELRIGHT and GRELBOTTOM),
  58.  *  the DEPTH gadgets are just GRELRIGHT).  The farthest left position is
  59.  *  recorded, and the Zoom Gadget is placed just to the left of that.
  60.  */
  61.  
  62. static void PositionZoomGadget(zGadget,theWindow)
  63. struct Gadget *zGadget;
  64. struct Window *theWindow;
  65. {
  66.    struct Gadget *theGadget = theWindow->FirstGadget;
  67.    int FarthestLeft = 1;
  68.    
  69.    while (theGadget)
  70.    {
  71.       if ((theGadget->Flags & (GRELRIGHT|GRELBOTTOM)) == GRELRIGHT &&
  72.            theGadget->TopEdge <= zGadget->Height &&
  73.            theGadget->LeftEdge < FarthestLeft)
  74.               FarthestLeft = theGadget->LeftEdge;
  75.       theGadget = theGadget->NextGadget;
  76.    }
  77.    zGadget->LeftEdge = FarthestLeft - zGadget->Width;
  78. }
  79.  
  80.  
  81. /*
  82.  *  AddZoomGadget()
  83.  *
  84.  *  Allocate a new Zoom Gadget structure, and initialize it for the proper
  85.  *  resolution of the window it is attached to.  Set the position of the
  86.  *  gadget so that it is to the left of the depth gadgets.  Then link it 
  87.  *  into the linked list of zoom gadgets so that we can keep track of it
  88.  *  (Forbid() so that the linked list does not change while we are using it).
  89.  *  Add the new gadget into the window, and refresh it so that it is 
  90.  *  displayed properly.  Since the gadget is added to the beginning of the
  91.  *  list, it will lie on top of the drag bar (if any).
  92.  */
  93.  
  94. static void AddZoomGadget(theWindow)
  95. struct Window *theWindow;
  96. {
  97.    ULONG Resolution = theWindow->WScreen->ViewPort.Modes & HIRES;
  98.    struct ExtGadget *theGadget;
  99.    
  100.    theGadget = AllocMem(EXTGADGETSIZE,MEMFLAGS);
  101.    if (theGadget)
  102.    {
  103.       theGadget->Window = theWindow;
  104.       theGadget->Flags = 0;
  105.       if (Resolution == HIRES)
  106.          theGadget->Gadget = ZoomGadget.Gadget;
  107.         else
  108.          theGadget->Gadget = LR_ZoomGadget.Gadget;
  109.       PositionZoomGadget(&(theGadget->Gadget),theWindow);
  110.       if (theWindow->Flags & GIMMEZEROZERO)
  111.          theGadget->Gadget.GadgetType |= GZZGADGET;
  112.  
  113.       Forbid();
  114.       theGadget->Prev = NULL;
  115.       theGadget->Next = FirstZoom;
  116.       if (FirstZoom) FirstZoom->Prev = theGadget;
  117.       FirstZoom = theGadget;
  118.       Permit();
  119.  
  120.       AddGadget(theWindow,&(theGadget->Gadget),0);
  121.       RefreshGList(&(theGadget->Gadget),theWindow,NULL,1);
  122.    }
  123. }
  124.  
  125.  
  126. /*
  127.  *  cOpenWindow()
  128.  *
  129.  *  This is called after a window has been opened:  theWindow is the 
  130.  *  pointer to the opened window.
  131.  *
  132.  *  If the window gets NEWSIZE IntuiMessages, or if it includes a SIZING
  133.  *  gadget, then add the Zoom Gadget.  We assume that windows that do not
  134.  *  include one of these are not allowed to change size, so we don't add
  135.  *  Zoom Gadgets to them.
  136.  */
  137.  
  138. struct Window *cOpenWindow(theWindow)
  139. struct Window *theWindow;
  140. {
  141.    if (theWindow)
  142.    {
  143.       if ((theWindow->IDCMPFlags & NEWSIZE) ||
  144.           (theWindow->Flags & WINDOWSIZING))
  145.               AddZoomGadget(theWindow);
  146.    }
  147.    return(theWindow);
  148. }
  149.  
  150.  
  151. /*
  152.  *  FindZoomGadget()
  153.  *
  154.  *  Look through the linked list for a gadget attached to this window
  155.  *  (alternatively, we could look through the window's gadget list for
  156.  *  one that has the ZOOMGADG Id, but this is probably safer).
  157.  *  Do this in Forbid() mode so that the list does not change while
  158.  *  we are looking at it.
  159.  */
  160.  
  161. static struct ExtGadget *FindZoomGadget(theWindow)
  162. struct Window *theWindow;
  163. {
  164.    struct ExtGadget *theGadget;
  165.    
  166.    Forbid();
  167.    theGadget = FirstZoom;
  168.    while (theGadget && theGadget->Window != theWindow)
  169.       theGadget = theGadget->Next;
  170.    Permit();
  171.    return(theGadget);
  172. }
  173.  
  174.  
  175. /*
  176.  *  cCloseWindow()
  177.  *
  178.  *  This is called before the window is closed.
  179.  *
  180.  *  If a window is being closed, check to see if it has a Zoom Gadget.
  181.  *  If so, then remove the gadget from the window, unlink it from
  182.  *  the linked list of gadgets, and free its memory.  This is done in
  183.  *  Forbid() mode so that the linked list of zoom gadgets does not change
  184.  *  while we are looking at it.
  185.  */
  186.  
  187. void cCloseWindow(theWindow)
  188. struct Window *theWindow;
  189. {
  190.    struct ExtGadget *theGadget;
  191.  
  192.    if (theWindow)
  193.    {
  194.       Forbid();
  195.       theGadget = FindZoomGadget(theWindow);
  196.       if (theGadget)
  197.       {
  198.          RemoveGadget(theWindow,&(theGadget->Gadget));
  199.          if (theGadget->Next) theGadget->Next->Prev = theGadget->Prev;
  200.          if (theGadget->Prev) theGadget->Prev->Next = theGadget->Next;
  201.          if (theGadget == FirstZoom) FirstZoom = theGadget->Next;
  202.          FreeMem(theGadget,EXTGADGETSIZE);
  203.       }
  204.       Permit();
  205.    }
  206. }
  207.  
  208.  
  209. /*
  210.  *  CheckZoomMove()
  211.  *
  212.  *  Called when a new gadget is being added to a window, this checks to
  213.  *  see if it is first in the gadget list and that it is being added to
  214.  *  a window (not a screen or requester).  If so, look for a zoom gadget
  215.  *  attached to this window.  If one exists, then remove it temporarily,
  216.  *  reposition it in relation to other GRELRIGHT gadgets, and then add it
  217.  *  back at the front of the list (make sure it's displayed on top).
  218.  *  Ten refresh the display so that the old image is removed and the new
  219.  *  one is displayed.
  220.  */
  221.  
  222. static void CheckZoomMove(theParent,theGadget,Position)
  223. struct Window *theParent;
  224. struct Gadget *theGadget;
  225. int Position;
  226. {
  227.    struct ExtGadget *zGadget;
  228.  
  229.    if (Position == 0 && (theGadget->GadgetType & (SCRGADGET|REQGADGET)) == 0)
  230.    {
  231.       zGadget = FindZoomGadget(theParent);
  232.       if (zGadget && theGadget != &(zGadget->Gadget))
  233.       {
  234.          RemoveGadget(theParent,&(zGadget->Gadget));
  235.          PositionZoomGadget(&(zGadget->Gadget),theParent);
  236.          aOldAddGadget(theParent,&(zGadget->Gadget),0);
  237.          RefreshWindowFrame(theParent);
  238.       }
  239.    }
  240. }
  241.  
  242.  
  243. /*
  244.  *  cAddGadget()
  245.  *
  246.  *  This is called before the gadget is added, and we are expected to call
  247.  *  aOldAddGadget somewhere in this routine.  The return address is the
  248.  *  position of the new gadget in the list.
  249.  *
  250.  *  First we add the new gadget into the list, then check the list for
  251.  *  Zoom Gadgets and reposition them as needed.
  252.  */
  253.  
  254. int cAddGadget(theParent,theGadget,Position)
  255. struct Window *theParent;
  256. struct Gadget *theGadget;
  257. int Position;
  258. {
  259.    Position = aOldAddGadget(theParent,theGadget,Position);
  260.    CheckZoomMove(theParent,theGadget,Position);
  261.    return(Position);
  262. }
  263.  
  264.  
  265. /*
  266.  *  cAddGList()
  267.  *
  268.  *  This is called before the gadgets are added, and we are expected to call
  269.  *  aOldAddGList somewhere in this routine.  The return address is the
  270.  *  position of the new gadgets in the list.
  271.  *
  272.  *  First we add the new gadgets into the list, then check the list for
  273.  *  Zoom Gadgets and reposition them as needed.
  274.  */
  275.  
  276. int cAddGList(theParent,theGadget,Position,Count,theRequest)
  277. struct Window *theParent;
  278. struct Gadget *theGadget;
  279. int Position;
  280. int Count;
  281. struct Requester *theRequest;
  282. {
  283.    Position = aOldAddGList(theParent,theGadget,Position,Count,theRequest);
  284.    CheckZoomMove(theParent,theGadget,Position);
  285.    return(Position);
  286. }
  287.  
  288. /*
  289.  *  ResizeWindow()
  290.  *
  291.  *  This routine provides a safe way to resize and move a window (the size
  292.  *  and position may be changed in order to make the window fit the screen).
  293.  *
  294.  *  Check to be sure the width and height are mot too big.
  295.  *  Check to be sure the position makes the whole window fit on the screen.
  296.  *
  297.  *  Calculate the offsets needed to make the window the right size and place
  298.  *  If the new widths would take it off the screen,
  299.  *    Move the window to its new position, and set the offsets to zero.
  300.  *  Size the window to make it the new size.
  301.  *  Move the window to its new position.
  302.  */
  303.  
  304. static void ResizeWindow(theWindow,x,y,w,h)
  305. struct Window *theWindow;
  306. int x,y,w,h;
  307. {
  308.    struct Screen *theScreen = theWindow->WScreen;
  309.    int dx,dy,dh,dw;
  310.  
  311.    if (w < 0) w = theScreen->Width; else
  312.    if (w > theScreen->Width)  w = theScreen->Width;
  313.    if (h < 0) h = theScreen->Height; else
  314.    if (h > theScreen->Height) h = theScreen->Height;
  315.    
  316.    if (x < 0) x = 0; else
  317.    if (x + w > theScreen->Width)  x = theScreen->Width  - w;
  318.    if (y < 0) y = 0; else
  319.    if (y + h > theScreen->Height) y = theScreen->Height - h;
  320.  
  321.    dx = x - theWindow->LeftEdge; dy = y - theWindow->TopEdge;
  322.    dw = w - theWindow->Width; dh = h - theWindow->Height;
  323.  
  324.    if (theWindow->LeftEdge + w > theScreen->Width ||
  325.        theWindow->TopEdge  + h > theScreen->Height)
  326.    {
  327.       MoveWindow(theWindow,dx,dy);
  328.       dx = dy = 0;
  329.    }
  330.    if (dw || dh) SizeWindow(theWindow,dw,dh);
  331.    if (dx || dy) MoveWindow(theWindow,dx,dy);
  332. }
  333.  
  334.  
  335. /*
  336.  *  ZoomOutWindow()
  337.  *
  338.  *  If the window has already been zoomed,
  339.  *    Resize the window to its original size.
  340.  *    Mark the window as not ZOOMED.
  341.  *  Otherwise the window should be sized to the full size of the screen.
  342.  *    If the window is not zoomed in then
  343.  *      Save the window's current position and size.
  344.  *    Zoom the window out to the size of the screen.
  345.  *    Mark the window as ZOOMED.
  346.  */
  347.  
  348. static void ZoomOutWindow(theGadget)
  349. struct ExtGadget *theGadget;
  350. {
  351.    struct Window *theWindow = theGadget->Window;
  352.  
  353.    if (theGadget->Flags & EG_ZOOMEDOUT)
  354.    {
  355.       ResizeWindow(theWindow,theGadget->x,theGadget->y,
  356.                              theGadget->w,theGadget->h);
  357.       theGadget->Flags = 0;
  358.    } else {
  359.       if ((theGadget->Flags & EG_ZOOMED) == 0)
  360.       {
  361.          theGadget->x = theWindow->LeftEdge;
  362.          theGadget->y = theWindow->TopEdge;
  363.          theGadget->w = theWindow->Width;
  364.          theGadget->h = theWindow->Height;
  365.       }
  366.       ResizeWindow(theWindow,0,0,theWindow->MaxWidth,theWindow->MaxHeight);
  367.       theGadget->Flags = EG_ZOOMEDOUT;
  368.    }
  369. }
  370.  
  371.  
  372. /*
  373.  *  ZoomInWindow()
  374.  *
  375.  *  If the window has already been zoomed,
  376.  *    Resize the window to its original size.
  377.  *    Mark the window as not ZOOMED.
  378.  *  Otherwise the window should be sized to its minimum size.
  379.  *    If the window is not zoomed out then
  380.  *      Save the window's current position and size.
  381.  *    Zoom the window to its smallest size.
  382.  *    Mark the window as ZOOMED.
  383.  */
  384.  
  385. static void ZoomInWindow(theGadget)
  386. struct ExtGadget *theGadget;
  387. {
  388.    struct Window *theWindow = theGadget->Window;
  389.    int w,h;
  390.  
  391.    if (theGadget->Flags & EG_ZOOMEDIN)
  392.    {
  393.       ResizeWindow(theWindow,theGadget->x,theGadget->y,
  394.                              theGadget->w,theGadget->h);
  395.       theGadget->Flags = 0;
  396.    } else {
  397.       if ((theGadget->Flags & EG_ZOOMED) == 0)
  398.       {
  399.          theGadget->x = theWindow->LeftEdge;
  400.          theGadget->y = theWindow->TopEdge;
  401.          theGadget->w = theWindow->Width;
  402.          theGadget->h = theWindow->Height;
  403.       }
  404.       w = MAX(theWindow->MinWidth,-theGadget->Gadget.LeftEdge);
  405.       h = MAX(theWindow->MinHeight,theGadget->Gadget.Height);
  406.       ResizeWindow(theWindow,theWindow->LeftEdge,theWindow->TopEdge,w,h);
  407.       theGadget->Flags = EG_ZOOMEDIN;
  408.    }
  409. }
  410.  
  411.  
  412. /*
  413.  *  PressedZoomGadget()
  414.  *
  415.  *  Finds the Zoom Gadget that is currently selected (if any).
  416.  *  This is called from an Input Handler whenever a SELECTUP button
  417.  *  event is passed to Intuition.  Intuition maintains the SELECTED flag
  418.  *  for the Zoom Gadgets and since the ZOOM gadgets are RELVERY BOOLGADGETs
  419.  *  they will be marked SELECTED whenever the mouse is pressed and held, and
  420.  *  as long as the mouse is over the gadget itself.  Thus if we find a
  421.  *  selected Zoom Gadget when the left mouse button is being released,
  422.  *  we can be pretty sure that the user is letting go of the Zoom Gadget
  423.  *  while the mouse is still over it, and thus we should process the
  424.  *  gadget hit.  This is done in Forbid() mode so that the linked list does
  425.  *  not change while we are looking at it.
  426.  */
  427.  
  428. static struct ExtGadget *PressedZoomGadget()
  429. {
  430.    struct ExtGadget *theGadget;
  431.    
  432.    Forbid();
  433.    theGadget = FirstZoom;
  434.    while (theGadget && (theGadget->Gadget.Flags & SELECTED) == 0)
  435.       theGadget = theGadget->Next;
  436.    Permit();
  437.    return(theGadget);
  438. }
  439.  
  440.  
  441. /*
  442.  *  ZoomHandler()
  443.  *
  444.  *  This is the Input Handler that checks for Zoom Gadget hits.  As described
  445.  *  in PressedZoomGadget() above, every time the left or right mouse button is 
  446.  *  released, we check to see if a Zoom Gadget is SELECTED, and assume that
  447.  *  that gadget is being released.  If such a gadget is found, then the
  448.  *  window it is attached to is zoomed.  The button event is still passed
  449.  *  to Intuition so that it will know that the mouse is no longer pressed,
  450.  *  and will deactivate the gadget.
  451.  *
  452.  *  Since the Zoom Gadgets are marked as SYSGADGETs, Intuition will not
  453.  *  send any IntuiMessages to the application about the Zoom Gadget, but since
  454.  *  their types are none of the standard Intuition gadgets, Intuition 
  455.  *  ignores them.  This saves having to monitor each windows IDCMP port for
  456.  *  messages from these gadgets, which reduces the overhead both in time and
  457.  *  programming.
  458.  */
  459.  
  460. struct InputEvent *ZoomHandler(EventList,data)
  461. struct InputEvent *EventList;
  462. APTR data;
  463. {
  464.    struct InputEvent *theEvent = EventList;
  465.    struct ExtGadget *theGadget;
  466.    
  467.    while (theEvent)
  468.    {
  469.       if (theEvent->ie_Class == IECLASS_RAWMOUSE &&
  470.          (theEvent->ie_Code  == SELECTUP || theEvent->ie_Code == MENUDOWN))
  471.       {
  472.          theGadget = PressedZoomGadget();
  473.          if (theGadget)
  474.             if (theEvent->ie_Code == MENUDOWN)
  475.             {
  476.                ZoomInWindow(theGadget);
  477.                theEvent->ie_Code = SELECTUP;
  478.             } else {
  479.                ZoomOutWindow(theGadget);
  480.             }
  481.       }
  482.       theEvent = theEvent->ie_NextEvent;
  483.    }
  484.    return(EventList);
  485. }
  486.